Visualizing Hurricane Ian Using hvPlot#

Within this post, we explore how we can use hvPlot to plot data from Hurricane Ian, which will soon make landfall in Florida. By the end of this post, you will be able to recreate the following plot: Hurricane Ian Plot

Imports#

import cartopy.crs as ccrs
import geopandas as gpd
import fiona

from siphon.simplewebservice.ndbc import NDBC
import hvplot.pandas
fiona.drvsupport.supported_drivers['libkml'] = 'rw' # enable KML support which is disabled by default
fiona.drvsupport.supported_drivers['LIBKML'] = 'rw' # enable KML support which is disabled by default

Access the Data#

We are using a few different datasets here. Let’s start with the hurricane forecast from the National Hurricane Center, accessible from their Geographic Information Systems (GIS) webpage:

We need to select the kmz files (a Google GIS file standard for the Hurricane Ian cone and track.

hurricane_cone = gpd.read_file("../data/AL092022_CONE_latest.kmz")
hurricane_track = gpd.read_file("../data/AL092022_TRACK_latest.kmz")
hurricane_track = hurricane_track.dropna(subset=["TCInitLocation"])

Investigate the GeoDataframe#

Let’s check out the geodataframe. Notice how it looks like a typical dataframe, with additional geometry information.

hurricane_cone
Name description timestamp begin end altitudeMode tessellate extrude visibility drawOrder ... stormType advisoryDate basin fcstpd storm atcfid advisoryNum stormNum stormName geometry
0 None None NaT NaT NaT None -1 0 -1 None ... HU 800 PM EDT Tue Sep 27 2022 AL 120 Hurricane Ian AL092022 19A 9 Ian POLYGON Z ((-83.04900 24.14015 0.00000, -83.02...

1 rows × 22 columns

hurricane_cone.geometry.plot();
../../../_images/9bbaf8e2c7c7e41ff5051f5055ed4a635142c3e14c08dc51cbd13f497c1ca26e.png

Access NOAA Buoy Data#

The National Oceanic and Atmospheric Administation (NOAA) has a buoy dataset (from the National Data Buoy Center), which includes observations from around the world. We can access this data using siphon, a tool developed by the Unidata Program Center which makes accessing this dataset much easier.

We can use the .lastest_observations() method from the NDBC module to access the latest data.

buoy_df = NDBC.latest_observations()
buoy_df
station latitude longitude wind_direction wind_speed wind_gust wave_height dominant_wave_period average_wave_period dominant_wave_direction pressure 3hr_pressure_tendency air_temperature water_temperature dewpoint visibility water_level_above_mean time
0 13009 8.000 -38.000 224.0 3.1 NaN NaN NaN NaN NaN NaN NaN 28.4 NaN NaN NaN NaN 2022-09-27 23:00:00+00:00
1 15002 0.000 -10.000 156.0 6.0 NaN NaN NaN NaN NaN NaN NaN 24.8 25.3 NaN NaN NaN 2022-09-27 22:00:00+00:00
2 22101 37.240 126.020 120.0 3.0 NaN 0.0 11.0 NaN NaN NaN NaN 21.1 21.1 NaN NaN NaN 2022-09-28 00:00:00+00:00
3 22102 34.790 125.780 160.0 3.0 NaN 0.0 11.0 NaN NaN NaN NaN 19.8 20.6 NaN NaN NaN 2022-09-28 00:00:00+00:00
4 22103 34.000 127.500 60.0 5.0 NaN 0.5 4.0 NaN NaN NaN NaN 22.5 23.4 NaN NaN NaN 2022-09-28 00:00:00+00:00
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 WYCM6 30.326 -89.326 10.0 6.7 8.2 NaN NaN NaN NaN 1017.1 1.0 27.4 26.2 NaN NaN NaN 2022-09-28 00:00:00+00:00
887 YATA2 59.548 -139.733 NaN NaN NaN NaN NaN NaN NaN 1012.9 0.4 NaN 12.0 NaN NaN NaN 2022-09-28 00:00:00+00:00
888 YKRV2 37.251 -76.342 320.0 3.6 4.1 NaN NaN NaN NaN 1015.4 2.1 21.8 NaN NaN NaN NaN 2022-09-28 00:00:00+00:00
889 YKTV2 37.227 -76.479 290.0 2.1 3.1 NaN NaN NaN NaN 1015.0 2.2 20.7 23.6 NaN NaN NaN 2022-09-28 00:00:00+00:00
890 YRSV2 37.414 -76.712 250.0 1.0 NaN NaN NaN NaN NaN 1015.0 NaN 17.6 NaN 9.4 NaN NaN 2022-09-27 23:30:00+00:00

891 rows × 18 columns

Filter the Dataset#

We are interested in locations that have water_temperature values, so we filter using .dropna()

buoy_df = buoy_df.dropna(subset=["water_temperature"])
buoy_df.plot.scatter(x='longitude', y='latitude', c='water_temperature')
<AxesSubplot: xlabel='longitude', ylabel='latitude'>
../../../_images/92eec37d677ea9bfa6ad284d826ccd6d3ca3f98e639ca4420c8e7e8ada46a143.png

Plot our Data using hvPlot#

Let’s move to interactive visualization!

Plot the Hurricane Cone and Track Using hvPlot#

We can do better than just static plots - let’s create an interactive one using hvPlot!

hurricane_cone.hvplot(color='None',
                      line_width=3,
                      coastline=True,
                      xlim=(-95, -65),
                      ylim=(20, 40),
                      label='NHC Forecast Cone for Hurricane Ian',
                      projection=ccrs.PlateCarree(),
                      features=["land", "ocean"])

And the same for the best estimated track

hurricane_track_plot = hurricane_track.hvplot(line_color='Red',
                                              color="None",
                                              line_width=3,
                                              coastline=True,
                                              xlim=(-95, -65),
                                              ylim=(20, 40),
                                              label='NHC Forecast Track for Hurricane Ian',
                                              projection=ccrs.PlateCarree(),
                                              features=["land", "ocean"])
hurricane_track_plot

We still need a title though, since this does not tell us what time this is valid… this information is in the dataframe!

hurricane_cone.advisoryDate
0    800 PM EDT Tue Sep 27 2022
Name: advisoryDate, dtype: object

Combine our Forecast Cone and Track Plots#

Let’s add the titles, and combine our plots.

hurricane_track_plot = hurricane_track.hvplot(line_color='Red',
                                              color="None",
                                              line_width=3,
                                              coastline=True,
                                              xlim=(-95, -65),
                                              ylim=(20, 40),
                                              title=f'NHC Forecast Valid: {hurricane_track.pubAdvTime.values[0]}',
                                              label='NHC Forecast Track for Hurricane Ian',
                                              projection=ccrs.PlateCarree()
                                             )

hurricane_cone_plot = hurricane_cone.hvplot(color='None',
                                            line_width=3,
                                            line_color='Black',
                                            coastline=True,
                                            xlim=(-95, -65),
                                            ylim=(20, 40),
                                            title=f"NHC Forecast Valid {hurricane_cone.advisoryDate.values[0]}",
                                            label='NHC Forecast Cone for Hurricane Ian',
                                            projection=ccrs.PlateCarree(),
                                            features=["land", "ocean"])

hurricane_plot = (hurricane_cone_plot * hurricane_track_plot)
hurricane_plot

Plot the Buoy Data using hvPlot#

buoy_plot = buoy_df.hvplot.points(x='longitude',
                                  y='latitude',
                                  c='water_temperature',
                                  cmap='inferno',
                                  label='NOAA Buoy Locations',
                                  title='NOAA Buoy Water Temperature',
                                  clabel='Temperature (degC)',
                                  geo=True,
                                  coastline=True,
                                  projection=ccrs.PlateCarree(),
                                  xlim=(-95, -65),
                                  ylim=(20, 40),
                                  clim=(20, 35))
buoy_plot

Final Visualization#

Let’s put it all together! We combine our plots using the * operator.

hurricane_plot * buoy_plot

Conclusions#

Within this example, we explored visualizing data from the National Hurricane Center, and from the National Data Buoy Center. We encourage you to try this out on your own.

In the future, it would be nice to add other datasets, such as weather radar data, onto these plots as well.